// Application - the class which kicks off the main GUI loop
// Copyright 2004 (C) Ralph Thomas

#ifndef APPLICATION_H
#define APPLICATION_H

#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <string>

namespace toolkit {
	//
	/// This functor can be passed to the application object
	/// and it will execute it in the main thread. This is
	/// useful for worker threads to pass messages back to
	/// the main thread when they have completed their work.
	//
	typedef boost::function<void (void)> thread_function_t;
	//
	/// This functor can be passed to the application object
	/// and it will be called when a file in a monitored
	/// directory changes.
	//
	typedef boost::function<void (const std::string&)> file_change_function_t;
	//
	/// This is the connection to a file monitor.
	//
	struct monitor_data_t;
	typedef boost::shared_ptr<monitor_data_t> monitor_connection_t;
	//
	/// The application class is the first class which any
	/// toolkit-using app should request. It will connect
	/// to the display server (not required on Win32) and
	/// do any other startup initialization stuff.
	///
	/// The main-loop also lives in here, and it is through
	/// this interface that idle callbacks can be registered.
	//
	class application {
	  public:
		virtual ~application();
		//
		// application& getInstance()
		//
		/// The application is a singleton object, and this
		/// method returns that instance. There are actually
		/// several implementations of this method, you will
		/// end up calling the one which works for the toolkit
		/// on your computer.
		///
		/// \return	the single application instance
		//
		static application& getInstance();
		//
		// void error(detail)
		//
		/// Display a modal fatal error dialog box. The app
		/// doesn't have to be in the main loop for this.
		///
		/// \param	detail	the message to display.
		//
		static void error(const std::string& detail);
		//
		/// The application object should be initialized before
		/// the run method is invoked. The initialization 
		/// process can generate errors, and these are they.
		//
		enum initReturn {
			kOk,		///< No error, application initialized
			kNoServer	///< Couldn't contact display server
		};
		//
		// initReturn init()
		//
		/// This function will initialize the application object
		/// if it hasn't already been initialized, and will return
		/// and error code if errors were encountered.
		///
		/// \return	any of the initReturn values
		//
		virtual initReturn init() = 0;
		//
		// void run()
		//
		/// Start the main loop of the program. When the program is
		/// done, the main loop returns.
		//
		virtual void run() = 0;
		//
		// void quit()
		//
		/// This method causes the application to exit graciously.
		/// Instead of the mainloop going around again, it will
		/// return to the caller of run.
		///
		/// \sa	run
		//
		virtual void quit() = 0;
		//
		// void doIdle()
		//
		/// Force some idle processing to happen.
		//
		virtual void doIdle() = 0;
		//
		// void executeInMain( const thread_function_t& f )
		// 
		/// Schedule the given function for execution in the main
		/// thread. Typically this will happen in under 1/10sec, but
		/// could take longer if the main thread is busy (doing
		/// something that should be in another thread!).
		///
		/// \param	f	the function to execute in the main
		///			thread.
		//
		virtual void executeInMain( const thread_function_t& f ) = 0;
		//
		// void monitor( const boost::filesystem::path& p, const file_change_function_t& f )
		//
		/// Monitor the given directory for changes. If a file
		/// inside the given directory changes then the given
		/// function will be called.
		///
		/// \param	uri	the URI of the directory to monitor.
		/// \param	f	the function to call when a child of the
		///				directory changes.
		//
		virtual monitor_connection_t monitor( const std::string& uri, const file_change_function_t& f, bool directory) = 0;
	};
};

#endif

